package com.gopay.bis.service.bank.failfeature.impl;


import com.gopay.bis.dao.bankorder.BisBankRspCodeFeatureDao;
import com.gopay.bis.service.bank.failfeature.BisBankFailFeatureService;
import com.gopay.common.domain.bank.bcdl.BisBankRspCodeFeature;
import com.gopay.remote.bank.BisBankFailFeatureRemoteService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 操作BisBankRspCodeFeature的service
 * Created by zyt on 2017/9/26.
 */
@Service("bisBankFailFeatureService")
public class BisBankFailFeatureServiceImpl implements BisBankFailFeatureService, BisBankFailFeatureRemoteService {

    private static Logger logger = LoggerFactory.getLogger(BisBankFailFeatureServiceImpl.class);

    @Resource(name = "bisBankRspCodeFeatureDao")
    private BisBankRspCodeFeatureDao bisBankRspCodeFeatureDao;

    //拼接key的分隔符
    private static final String SPLIT_SYMBOL = ":";
    //数据库中isFail代表失败的码
    private static final String FAILED_CODE = "1";
    //数据库中isFail代表成功的码
    private static final String NOTFAILED_CODE = "0";

    private Map<String, Boolean> failCodeMap = new HashMap<>();


    @Override
    public boolean checkIsOrderFailed(String bankCode, String transType, String returnCode, String dealResult){
        String key = makeKeyByInfo(bankCode, transType, returnCode, dealResult);
        if(failCodeMap.containsKey(key) && failCodeMap.get(key).equals(Boolean.TRUE)){
            return true;
        }
        return false;
    }

    @Override
    public BisBankRspCodeFeature insertBisBankFailFeature(String bankCode, String transType
            , String returnCode, String dealResult, String needRefund, String description) {
        BisBankRspCodeFeature bisBankRspCodeFeature = new BisBankRspCodeFeature();
        bisBankRspCodeFeature.setBankCode(bankCode);
        bisBankRspCodeFeature.setTransCode(transType);
        bisBankRspCodeFeature.setResponseCode(returnCode);
        bisBankRspCodeFeature.setOrderCode(dealResult);
        bisBankRspCodeFeature.setDecription(description);
        bisBankRspCodeFeature.setIsFail(needRefund);
        bisBankRspCodeFeature.setCreateTs(new Date());
        bisBankRspCodeFeature.setLastUpdateTs(new Date());

        bisBankRspCodeFeatureDao.save(bisBankRspCodeFeature);
        return bisBankRspCodeFeature;
    }

    @Override
    public BisBankRspCodeFeature modifiedBisBankFailFeature(BisBankRspCodeFeature newBisBankRspCodeFeature) {
        bisBankRspCodeFeatureDao.update(newBisBankRspCodeFeature);
        return newBisBankRspCodeFeature;
    }

    @Override
    public void deleteBisBankFailFeature(BisBankRspCodeFeature bisBankRspCodeFeature) {
        bisBankRspCodeFeatureDao.delete(bisBankRspCodeFeature);
    }

    @Override
    public List<BisBankRspCodeFeature> findBisBankFailFeature(String bankCode, String transType, String returnCode, String dealResult, Boolean needRefund) {
        StringBuffer hql = new StringBuffer("from BisBankRspCodeFeature where 1=1 ");
        Map<String, Object> params = new HashMap<>();
        if(StringUtils.isNotBlank(bankCode)){
            hql.append(" and bankCode = :bankCode ");
            params.put("bankCode", bankCode);
        }
        if(StringUtils.isNotBlank(transType)){
            hql.append(" and transCode = :transType ");
            params.put("transType", transType);
        }
        if(StringUtils.isNotBlank(returnCode)){
            hql.append(" and responseCode = :returnCode ");
            params.put("returnCode", returnCode);
        }
        if(StringUtils.isNotBlank(dealResult)){
            hql.append(" and orderCode = :dealResult ");
            params.put("dealResult", dealResult);
        }
        if(needRefund != null){
            hql.append(" and needRefund = :needRefund ");
            params.put("needRefund", needRefund ? FAILED_CODE : NOTFAILED_CODE);
        }
        return bisBankRspCodeFeatureDao.findByHql(hql.toString(), params);
    }

    @Override
    public BisBankRspCodeFeature findById(String id) {
        StringBuffer hql = new StringBuffer("from BisBankRspCodeFeature where id = :id ");
        Map<String, Object> params = new HashMap<>();
        params.put("id", Long.parseLong(id));
        return bisBankRspCodeFeatureDao.findByHql(hql.toString(), params).get(0);
    }


    /**
     * 加载类前自动运行任务
     */
    @PostConstruct
    private void initAutoReloadTask(){
        initFailCodeMap();
    }

    /**
     * 初始化失败订单特征map
     */
    private void initFailCodeMap(){
        HashMap<String, Boolean> map = new HashMap<>();
        List<BisBankRspCodeFeature> bisBankRspCodeFeatureList = bisBankRspCodeFeatureDao.findAll();
        for(BisBankRspCodeFeature bisBankRspCodeFeature : bisBankRspCodeFeatureList){
            String key = makeKeyByInfo(bisBankRspCodeFeature.getBankCode(), bisBankRspCodeFeature.getTransCode(),
                    bisBankRspCodeFeature.getResponseCode(), bisBankRspCodeFeature.getOrderCode());
            map.put(key, StringUtils.equals(bisBankRspCodeFeature.getIsFail(), FAILED_CODE) ? true : false);
        }

        if(failCodeMap == null){
            failCodeMap = new HashMap<>();
        }
        failCodeMap.clear();
        failCodeMap.putAll(map);
        logger.error("load bank failureFeature map :{}", failCodeMap);
    }

    /**
     * 根据信息拼接查询的key
     * @param bankCode      银行名称代码
     * @param transType     交易类型
     * @param returnCode    报文返回码
     * @param dealResult    订单结果码
     * @return              拼接的key值
     */
    public String makeKeyByInfo(String bankCode, String transType, String returnCode, String dealResult){
        return bankCode + SPLIT_SYMBOL + transType + SPLIT_SYMBOL
                + returnCode + SPLIT_SYMBOL +
                (StringUtils.isBlank(dealResult) ? "null" : dealResult);
    }

    //时间间隔
   /* private static final long PERIOD = 24 * 60 * 60 * 1000;
    //執行的時間：小時
    private static final int START_HOUR = 2;
    //執行的時間：分鐘
    private static final int START_MINITE = 0;
    //執行的時間：秒
    private static final int START_SECOND = 0;*/

    /**
     * 定时执行的任务
     */
    /*private void autoFailCodeMap(){
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, START_HOUR);
        calendar.set(Calendar.MINUTE, START_MINITE);
        calendar.set(Calendar.SECOND, START_SECOND);

        Date date = calendar.getTime();

        Date currentDate = new Date();

        long timeDelay = date.getTime() - currentDate.getTime();

        while(timeDelay <= 0){
            timeDelay = timeDelay + PERIOD;
        }

        Timer t = new Timer();
        t.schedule(new TimerTask(){
            public void run(){
                initFailCodeMap();
            }
        }, timeDelay, PERIOD);
    }*/
}
